import com.fasterxml.jackson.databind.ObjectMapper;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Iterator;

/**
 * Created by nacar on 19/01/14.
 */
public class TemplateEngine {
    private static ObjectMapper mapper = new ObjectMapper();
    private NamespaceRegistry namespaceRegistry;

    public TemplateEngine(NamespaceRegistry namespaceRegistry) {
        this.namespaceRegistry = namespaceRegistry;
    }

    public String parse(InputStream inputStream) {
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            Element root = document.getRootElement();
            TemplateContext context = new TemplateContext();
            context.setCurrentElement(root);
            context.setDocRoot(root);
            TemplateContext.set(context);
            Tag tag = parseElement();
            TemplateContext.remove();
            try {
                String json = mapper.writeValueAsString(tag);
                return json;
            } catch (Exception e) {
                System.out.println(e);
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    public String parse(String file) throws FileNotFoundException {
        FileInputStream fis = new FileInputStream(file);
        return parse(fis);
    }


    private Tag parseElement() {
        TemplateContext context = TemplateContext.getInstance();
        Element el = context.getCurrentElement();
        String namespace = el.getNamespaceURI(); // TODO Da risolvere in base al prefisso del tag


        String name = el.getName();
        TagRegistry registry = namespaceRegistry.get(namespace);
        if (registry == null) {
            throw new RuntimeException("Registro non trovato per il namespace " + namespace);
        }
        Tag tag = registry.get(name);
        if (tag == null) {
            throw new RuntimeException("Tag " + name + " non trovato nel namespace " + namespace);
        }
        if (context.getRoot() == null) {
            context.setRoot(tag);
        }
        tag.setElement(el);
        tag.startTag();

        for (Iterator i = el.attributeIterator(); i.hasNext(); ) {
            Attribute attribute = (Attribute) i.next();
            tag.addAttribute(attribute.getName(), attribute.getText());
        }

        for (Iterator i = el.elementIterator(); i.hasNext(); ) {
            Element element = (Element) i.next();
            context.setCurrentElement(element);

            Tag child = parseElement();
            context.setCurrentElement(el);
            tag.addChild(child);
        }
        context.setCurrentElement(el);
        String text = el.getText();
        tag.setTextContent(text);
        tag.endTag();
        return tag;
    }


}
